#include<ctime>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include"blockqueue.hpp"
#include"Task.hpp"
using namespace std;

int myadd(int x,int y)
{
    return x+y;
}
template<class C,class S>//C-cal，S-save
class blockqueues
{
public:
blockqueue<C>* c_bq;
blockqueue<S>* s_bq;
};

int mymath(int x,int y,char op)
{
    int ret=0;
    switch(op)
    {
        case '+':
      ret=x+y;
        break;

        case '-':
      ret=x-y;
        break;

        case '*':
      ret=x*y;
        break;

        case '/':
        {if(y==0)
        {
            cerr<<"div zero error!"<<endl;
            ret=-1;
        }else
        {
            ret=x/y;
        }
        }
        break;

        case '%':
        {if(y==0)
        {
            cerr<<"div zero error!"<<endl;
            ret=-1;
        }else
        {
            ret=x%y;
        }
        }
        break;
        default:
        //nothing
        break;
    }
    return ret;
}

const string oper="+-*/%";
void* provider(void* args)
{
    //blockqueue<Caltask>* bqs=static_cast<blockqueue<Task>*>(args);
 blockqueue<Caltask>* bqs=(static_cast<blockqueues<Caltask,SaveTask> *>(args))->c_bq;
while(true)
{
//int qu=rand()%10+1;
int x=rand()%100+1;//参数一设置随机数
int y=rand()%10+1;//参数二设置随机数
int opnum=rand()%oper.size();//随机运算符
Caltask ret(x,y,oper[opnum],mymath);//调用计算任务对象的仿函数
bqs->push(ret);
cout<<"供应商供应了任务："<<ret.tasktostringforP()<<endl;
 sleep(1);//供应商供应的慢，那么供应商供应一个，消费者消费一个
}
return nullptr;
}

void* consumer(void* args)
{
  //  blockqueue<Caltask>* bqs=static_cast<blockqueue<Task>*>(args);
    blockqueue<Caltask>* Cal_bqs=(static_cast<blockqueues<Caltask,SaveTask> *>(args))->c_bq;
    blockqueue<SaveTask>* Sav_bqs=(static_cast<blockqueues<Caltask,SaveTask> *>(args))->s_bq;
//参数类型原本是void*，然后转化为blockqueues<Caltask,SaveTask> *类型，然后取出里面的Caltask阻塞队列
    while(true)
    {
       // int ret=0;
       Caltask ret;
        Cal_bqs->pop(&ret);
        string result=ret();//调用计算任务对象的仿函数，用string接收返回值
        cout<<"计算任务是："<<result<<endl;//计算任务完成

        SaveTask sa(result,mysave);
        Sav_bqs->push(sa);//实际上是把参数传给SaveTask对象
        cout<<"消费者推送了保存任务："<<endl;
       // sleep(1);//消费者消费的慢，那么供应商先把阻塞队列填满，然后消费者在消费一个，供应商供应一个
    }
    return nullptr;
}

void* saver(void* args)
{
    blockqueue<SaveTask>*Sav_bqs=(static_cast<blockqueues<Caltask,SaveTask>*>(args))->s_bq;

while(true)
{
SaveTask ret;
Sav_bqs->pop(&ret);//把队列中的对象赋值给ret无参对象，即拷贝构造ret
ret();//调用Savetask对像的仿函数
cout<<"saver保存任务完成"<<endl;
}
return nullptr;
}

int main()
{
srand((unsigned long)time(nullptr)^getpid());
blockqueues<Caltask,SaveTask> bqs;//建立双线阻塞队列对象
bqs.c_bq=new blockqueue<Caltask>();//把对应阻塞队列的对象赋给双线阻塞队列对象的对应成员。阻塞队列中的对象类型是Caltask
bqs.s_bq=new blockqueue<SaveTask>();//阻塞队列中的对象类型是Savetask
//blockqueue<Task> *bq=new blockqueue<Task>();//建立队列
pthread_t c,p,s;
pthread_create(&c,nullptr,consumer,&bqs);//创建消费者线程
pthread_create(&c,nullptr,provider,&bqs);//创建供应商线程
pthread_create(&s,nullptr,saver,&bqs);//创建保存线程

pthread_join(c,nullptr);//回收消费者线程
pthread_join(p,nullptr);//回收供应商 线程
pthread_join(s,nullptr);//回收保存线程

delete bqs.c_bq;
delete bqs.s_bq;

return 0;
}